home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windows 95 API Bible
/
Windows 95 API Bible 3 Disc Set.iso
/
Win32 API Bible Book 2 of 3.iso
/
chapter8
/
rtfedit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-03-06
|
38KB
|
1,244 lines
#include <windows.h>
#include <excpt.h>
#include <richedit.h>
#include <commctrl.h>
#include "rtfedit.h"
#if defined (WIN32)
#define IS_WIN32 TRUE
#else
#define IS_WIN32 FALSE
#endif
#define IS_NT IS_WIN32 && (BOOL)(GetVersion() < 0x80000000)
#define IS_WIN32S IS_WIN32 && (BOOL)(!(IS_NT) && (LOBYTE(LOWORD(GetVersion()))<4))
#define IS_WIN95 (BOOL)(!(IS_NT) && !(IS_WIN32S)) && IS_WIN32
LPCTSTR lpszAppName = "MyApp";
LPCTSTR lpszTitle = "Rich-Text Editor";
HINSTANCE hInst; // current instance
HINSTANCE hRtfLib = NULL; // rich-text DLL instance
FINDREPLACE fr;
UINT nRTF; // registered clipboard format for RTF
HWND hMainWnd = NULL; // Window handle for the application
HWND hEdit = NULL; // Window handle of rich-text edit control
HWND hStatusWnd = NULL;
HWND hDlgAbort = NULL;
HWND hFindWnd = NULL;
BOOL bAbort = FALSE;
HANDLE ghDevMode = NULL;
HANDLE ghDevNames = NULL;
TCHAR szFindWhat[128];
#define MAXFILESIZE 0x000FFFFF
char szFileName[ MAX_PATH+1 ] = "\0";
LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
static RECT strect;
static UINT nFindMsg = 0;
if ( uMsg == nFindMsg )
{
HandleFindMsg( (FINDREPLACE*)lParam );
return( 0 );
}
switch( uMsg )
{
case WM_CREATE :
InitCommonControls();
szFindWhat[0] = '\0';
nFindMsg = RegisterWindowMessage( "commdlg_FindReplace" );
hRtfLib = LoadLibrary( "RICHED32.DLL" );
hEdit = CreateWindowEx( WS_EX_CLIENTEDGE,
"RICHEDIT",
"",
WS_CHILD | WS_VISIBLE |
WS_BORDER | ES_MULTILINE |
WS_VSCROLL | WS_HSCROLL |
ES_AUTOVSCROLL | ES_NOHIDESEL,
0, 0,
0, 0,
hWnd,
(HMENU)1,
hInst,
NULL );
hStatusWnd = CreateStatusWindow(
WS_CHILD | WS_VISIBLE |
CCS_BOTTOM | SBARS_SIZEGRIP,
"", hWnd, 101 );
// Register the RTF clipboard format.
//...................................
nRTF = RegisterClipboardFormat( CF_RTF );
// Set the default Font.
//......................
if ( hEdit )
{
CHARFORMAT cf;
DWORD dwEvent;
cf.cbSize = sizeof( CHARFORMAT );
cf.dwMask = CFM_FACE | CFM_BOLD | CFM_UNDERLINE |
CFM_ITALIC | CFM_COLOR;
cf.dwEffects = CFE_AUTOCOLOR;
strcpy( cf.szFaceName, "Arial" );
SendMessage( hEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf );
SetFocus( hEdit );
// Set the event mask to return EN_SELCHANGE.
//...........................................
dwEvent = SendMessage( hEdit, EM_GETEVENTMASK, 0, 0 );
dwEvent |= ENM_SELCHANGE;
SendMessage( hEdit, EM_SETEVENTMASK, 0, dwEvent );
// Set the maximum number of characters.
//......................................
SendMessage( hEdit, EM_EXLIMITTEXT, 0, MAXFILESIZE );
}
// Retrieve the status window size.
//.................................
if ( hStatusWnd )
GetClientRect( hStatusWnd, &strect );
break;
case WM_SETFOCUS :
SetFocus( hEdit );
break;
case WM_SIZE :
// Size the status window.
//........................
if ( hStatusWnd )
{
int nParts[2];
MoveWindow( hStatusWnd, 0, HIWORD( lParam )-strect.bottom,
LOWORD( lParam ), HIWORD( lParam ), FALSE );
nParts[0] = LOWORD( lParam )-120;
nParts[1] = -1;
SendMessage( hStatusWnd, SB_SETPARTS, 2, (LPARAM)nParts );
}
// Size the edit window.
//......................
if ( hEdit )
MoveWindow( hEdit,0,0, LOWORD(lParam),
HIWORD(lParam)-strect.bottom, TRUE );
break;
case WM_INITMENUPOPUP :
switch( LOWORD( lParam ) )
{
case 0 : HandleFileMenu( (HMENU)wParam ); break;
case 1 : HandleEditMenu( (HMENU)wParam ); break;
case 2 : HandleFormatMenu( (HMENU)wParam ); break;
}
break;
case WM_NOTIFY :
switch( ((NMHDR*)lParam)->code )
{
case EN_SELCHANGE :
HandleSelChange( &((SELCHANGE*)lParam)->chrg );
break;
case EN_SAVECLIPBOARD :
if ( MessageBox( hWnd,
"Data is on the clipboard.\nDo you want to make it available?",
lpszTitle,
MB_YESNO | MB_ICONQUESTION ) == IDNO )
{
return( TRUE );
}
break;
case EN_STOPNOUNDO :
if ( MessageBox( hWnd,
"This operation is too big to be undone.\n" \
"Do you want to continue without undo?",
lpszTitle,
MB_YESNO | MB_ICONQUESTION ) == IDNO )
{
return( TRUE );
}
break;
}
break;
case WM_COMMAND :
switch( LOWORD( wParam ) )
{
// File menu items.
//.................
case IDM_NEW :
SendMessage( hEdit, WM_SETTEXT, 0, 0 );
SendMessage( hEdit, EM_SETMODIFY, 0, 0 );
break;
case IDM_OPEN : Open(); break;
case IDM_SAVE : Save(); break;
case IDM_SAVEAS: SaveAs(); break;
case IDM_PRINT : Print(); break;
case IDM_EXIT : DestroyWindow( hWnd ); break;
// Edit menu items.
//.................
case IDM_UNDO : SendMessage( hEdit, WM_UNDO, 0, 0 ); break;
case IDM_CUT : SendMessage( hEdit, WM_CUT, 0, 0 ); break;
case IDM_COPY : SendMessage( hEdit, WM_COPY, 0, 0 ); break;
case IDM_PASTE : PasteClipboard(); break;
case IDM_DELETE: SendMessage( hEdit, WM_CLEAR, 0, 0 ); break;
case IDM_SELECTALL :
{
CHARRANGE cr;
cr.cpMin = 0;
cr.cpMax = -1;
SendMessage( hEdit, EM_EXSETSEL, 0, (LPARAM)&cr );
}
break;
case IDM_FIND :
if ( !hFindWnd )
{
fr.lStructSize = sizeof( FINDREPLACE );
fr.hwndOwner = hWnd;
fr.lpstrFindWhat = szFindWhat;
fr.Flags = FR_NOUPDOWN;
fr.wFindWhatLen = sizeof( szFindWhat );
hFindWnd = FindText( &fr );
CommDlgExtendedError();
}
else
SetFocus( hFindWnd );
break;
case IDM_NEXTWORD :
{
CHARRANGE cr;
SendMessage( hEdit, EM_EXGETSEL, 0, (LPARAM)&cr );
// Retrieve the position of the next word.
//........................................
cr.cpMin = SendMessage( hEdit, EM_FINDWORDBREAK,
WB_RIGHT, cr.cpMax );
cr.cpMax = SendMessage( hEdit, EM_FINDWORDBREAK,
WB_RIGHTBREAK, cr.cpMin );
SendMessage( hEdit, EM_EXSETSEL, 0, (LPARAM)&cr );
}
break;
// Format menu items.
//...................
case IDM_BOLD :
case IDM_ITALIC :
case IDM_UNDERLINE :
ChangeCharFormat( LOWORD( wParam ) );
break;
case IDM_ALIGNLEFT :
case IDM_ALIGNCENTER :
case IDM_ALIGNRIGHT :
ChangeAlignment( LOWORD( wParam ) );
break;
case IDM_FONT :
ChangeFont();
break;
// Help menu items.
//.................
case IDM_ABOUT :
DialogBox( hInst, "AboutBox", hWnd, (DLGPROC)About );
break;
}
break;
case WM_DESTROY :
if ( ghDevMode ) GlobalFree( ghDevMode );
if ( ghDevNames ) GlobalFree( ghDevNames );
// Delete the edit window so the EN_SAVECLIPBOARD
// notification can be processed before it is too late.
//.....................................................
DestroyWindow( hEdit );
PostQuitMessage( 0 );
break;
default :
return( DefWindowProc( hWnd, uMsg, wParam, lParam ) );
}
return( 0L );
}
//***********************************************************
//***********************************************************
// Notification Handlers.
//.......................
VOID HandleFindMsg( FINDREPLACE* pFR )
{
if ( pFR->Flags & FR_FINDNEXT )
{
FINDTEXTEX ft;
LONG lPos;
UINT uFlags = pFR->Flags;
// Retrieve current position.
//...........................
SendMessage( hEdit, EM_EXGETSEL, 0, (LPARAM)&ft.chrg );
// Increment the position by 1 to skip where we are.
//..................................................
ft.chrg.cpMin++;
// Search to the end of the text.
//...............................
ft.chrg.cpMax = -1;
ft.lpstrText = pFR->lpstrFindWhat;
lPos = SendMessage( hEdit, EM_FINDTEXTEX, uFlags, (LPARAM)&ft );
if ( lPos > -1 )
SendMessage( hEdit, EM_EXSETSEL, 0, (LPARAM)&ft.chrgText );
else
MessageBox( hMainWnd, "Text not found.", "Find", MB_OK | MB_ICONINFORMATION );
}
// The user closed the Find dialog.
//.................................
if ( pFR->Flags & FR_DIALOGTERM )
hFindWnd = NULL;
}
VOID HandleSelChange( CHARRANGE* cr )
{
static char szTmp[32];
int nLineMin, nLineMax;
// Retrieve the line number of the positions.
//...........................................
nLineMin = SendMessage( hEdit, EM_LINEFROMCHAR,
cr->cpMin, 0 );
nLineMax = SendMessage( hEdit, EM_LINEFROMCHAR,
cr->cpMax, 0 );
// Display the line pos.
//......................
if ( cr->cpMin != cr->cpMax )
{
if ( nLineMin != nLineMax )
wsprintf( szTmp, "Ln %d:%d, Pos %d:%d",
nLineMin+1, nLineMax+1,
cr->cpMin+1,
cr->cpMax+1 );
else
wsprintf( szTmp, "Ln %d, Pos %d:%d",
nLineMin+1, cr->cpMin+1,
cr->cpMax+1 );
}
else
wsprintf( szTmp, "Ln %d, Pos %d",
nLineMin+1, cr->cpMin+1 );
SendMessage( hStatusWnd, SB_SETTEXT, 1, (LPARAM)szTmp );
}
//***********************************************************
//***********************************************************
// Menu item Initialize Functions.
//................................
VOID HandleFileMenu( HMENU hMenu )
{
// Set the save menu item.
//........................
EnableMenuItem( hMenu, IDM_SAVE, MF_BYCOMMAND |
SendMessage( hEdit, EM_GETMODIFY, 0, 0 ) ?
MF_ENABLED : MF_GRAYED );
}
VOID HandleEditMenu( HMENU hMenu )
{
CHARRANGE cr;
UINT uEnable;
// Set the Paste menu item.
//.........................
if ( OpenClipboard( hMainWnd ) )
{
// Check to see if one of these formats is available.
//...................................................
if ( IsClipboardFormatAvailable( CF_TEXT ) ||
IsClipboardFormatAvailable( nRTF ) )
EnableMenuItem( hMenu, IDM_PASTE, MF_BYCOMMAND | MF_ENABLED );
else
EnableMenuItem( hMenu, IDM_PASTE, MF_BYCOMMAND | MF_GRAYED );
CloseClipboard();
}
// Set the Cut/Copy/Delete menu items.
//.............................
SendMessage( hEdit, EM_EXGETSEL, 0, (LPARAM)&cr );
uEnable = cr.cpMin != cr.cpMax ? MF_ENABLED : MF_GRAYED;
EnableMenuItem( hMenu, IDM_CUT, MF_BYCOMMAND | uEnable );
EnableMenuItem( hMenu, IDM_COPY, MF_BYCOMMAND | uEnable );
EnableMenuItem( hMenu, IDM_DELETE, MF_BYCOMMAND | uEnable );
// Set the Select All menu item.
//..............................
if ( SendMessage( hEdit, WM_GETTEXTLENGTH, 0, 0 ) )
EnableMenuItem( hMenu, IDM_SELECTALL, MF_BYCOMMAND | MF_ENABLED );
else
EnableMenuItem( hMenu, IDM_SELECTALL, MF_BYCOMMAND | MF_GRAYED );
}
VOID HandleFormatMenu( HMENU hMenu )
{
CHARFORMAT cf;
PARAFORMAT pf;
cf.cbSize = sizeof( CHARFORMAT );
SendMessage( hEdit, EM_GETCHARFORMAT, TRUE, (LPARAM)&cf );
// Set the Bold/Italic/Underline menu items
//.........................................
if ( cf.dwMask & CFM_BOLD )
CheckMenuItem( hMenu, IDM_BOLD, MF_BYCOMMAND |
(cf.dwEffects & CFE_BOLD) ?
MF_CHECKED : MF_UNCHECKED );
if ( cf.dwMask & CFM_ITALIC )
CheckMenuItem( hMenu, IDM_ITALIC, MF_BYCOMMAND |
(cf.dwEffects & CFE_ITALIC) ?
MF_CHECKED : MF_UNCHECKED );
if ( cf.dwMask & CFM_UNDERLINE )
CheckMenuItem( hMenu, IDM_UNDERLINE, MF_BYCOMMAND |
(cf.dwEffects & CFE_UNDERLINE) ?
MF_CHECKED : MF_UNCHECKED );
pf.cbSize = sizeof( PARAFORMAT );
SendMessage( hEdit, EM_GETPARAFORMAT, TRUE, (LPARAM)&pf );
if ( pf.dwMask & PFM_ALIGNMENT )
CheckMenuRadioItem( hMenu, IDM_ALIGNLEFT, IDM_ALIGNRIGHT,
pf.wAlignment == PFA_LEFT ? IDM_ALIGNLEFT :
pf.wAlignment == PFA_CENTER ? IDM_ALIGNCENTER :
IDM_ALIGNRIGHT, MF_BYCOMMAND );
}
//***********************************************************
//***********************************************************
// Menu item handler Functions.
//.............................
DWORD CALLBACK ReadProc( DWORD dwCookie, LPBYTE pbBuff,
LONG cb, LONG* pcb )
{
// Read the data from the file.
//.............................
ReadFile( (HANDLE)dwCookie,
pbBuff, cb,
pcb,
NULL );
return( FALSE );
}
DWORD CALLBACK SaveProc( DWORD dwCookie, LPBYTE pbBuff,
LONG cb, LONG* pcb )
{
// Write the data to the file.
//............................
if ( WriteFile( (HANDLE)dwCookie,
pbBuff, cb,
pcb,
NULL ) )
{
return( TRUE );
}
return( FALSE );
}
VOID Open()
{
OPENFILENAME ofn;
memset( &ofn, 0, sizeof( OPENFILENAME ) );
// Fill OPENFILENAME structure.
//.............................
ofn.lStructSize = sizeof( OPENFILENAME );
ofn.hwndOwner = hMainWnd;
ofn.lpstrFilter = "Rich-Text File (*.RTF)\0*.RTF\0\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "RTF";
// Get a filename and save the file.
//..................................
if ( GetOpenFileName( &ofn ) )
{
EDITSTREAM es;
HANDLE hFile;
// Open the file.
//...............
hFile = CreateFile( szFileName, GENERIC_READ, 0, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
if ( hFile )
{
// Fill the EDITSTREAM structure.
//...............................
es.dwCookie = (DWORD)hFile;
es.dwError = 0;
es.pfnCallback = ReadProc;
// Read the data from the file.
//.............................
SendMessage( hEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es );
// Clear the modify flag.
//.......................
SendMessage( hEdit, EM_SETMODIFY, 0, 0 );
}
CloseHandle( hFile );
}
}
VOID Save()
{
// If there is no filename,
// go to save as.
//.........................
if ( !szFileName[0] )
SaveAs();
else
{
EDITSTREAM es;
HANDLE hFile;
// Create a new file, always.
//...........................
hFile = CreateFile( szFileName, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_WRITE_THROUGH,
NULL );
// Fill the EDITSTREAM structure.
//...............................
es.dwCookie = (DWORD)hFile;
es.dwError = 0;
es.pfnCallback = SaveProc;
// Save the data to the file.
//...........................
SendMessage( hEdit, EM_STREAMOUT, SF_RTF, (LPARAM)&es );
// Clear the modify flag.
//.......................
SendMessage( hEdit, EM_SETMODIFY, 0, 0 );
CloseHandle( hFile );
}
}
VOID SaveAs()
{
OPENFILENAME ofn;
memset( &ofn, 0, sizeof( OPENFILENAME ) );
// Fill OPENFILENAME structure.
//.............................
ofn.lStructSize = sizeof( OPENFILENAME );
ofn.hwndOwner = hMainWnd;
ofn.lpstrFilter = "Rich-Text File (*.RTF)\0*.RTF\0\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "RTF";
// Get a filename and save the file.
//..................................
if ( GetSaveFileName( &ofn ) )
Save();
}
VOID Print()
{
PRINTDLG pd;
// Default settings, these can change
// once the user has gone through the print process.
//..................................................
static DWORD Flags = PD_ALLPAGES | PD_SHOWHELP | PD_RETURNDC;
static WORD nFromPage = 0xFFFF;
static WORD nToPage = 0xFFFF;
static WORD nCopies = 1;
memset( &pd, 0, sizeof( PRINTDLG ) );
pd.lStructSize = sizeof(pd);
pd.hwndOwner = hMainWnd;
pd.hDevMode = ghDevMode;
pd.hDevNames = ghDevNames;
pd.Flags = Flags;
pd.nFromPage = nFromPage;
pd.nToPage = nToPage;
pd.nMinPage = 0;
pd.nMaxPage = 0xFFFF;
pd.nCopies = nCopies;
if ( PrintDlg(&pd) )
{
// Actually Print the document.
//.............................
PrintDocument( &pd );
// Save the settings as the defaults.
//...................................
ghDevMode = pd.hDevMode;
ghDevNames = pd.hDevNames;
Flags = pd.Flags;
nFromPage = pd.nFromPage;
nToPage = pd.nToPage;
nCopies = pd.nCopies;
}
}
VOID PasteClipboard()
{
if ( OpenClipboard( hMainWnd ) )
{
// Check if the clipboard format is RTF.
//......................................
BOOL bRTF = IsClipboardFormatAvailable( nRTF );
CloseClipboard();
// Paste the clipboard contents into the
// rich-text edit control.
// The RTF format is preferred.
//......................................
SendMessage( hEdit, EM_PASTESPECIAL,
bRTF ? nRTF : CF_TEXT, 0 );
}
SetFocus( hEdit );
}
VOID ChangeCharFormat( UINT uCmd )
{
CHARFORMAT cf;
// Retrieve the current setting.
//..............................
cf.cbSize = sizeof( CHARFORMAT );
SendMessage( hEdit, EM_GETCHARFORMAT, TRUE, (LPARAM)&cf );
// Toggle the appropriate format.
//...............................
switch( uCmd )
{
case IDM_BOLD :
cf.dwMask = CFM_BOLD;
cf.dwEffects ^= CFE_BOLD;
break;
case IDM_ITALIC :
cf.dwMask = CFM_ITALIC;
cf.dwEffects ^= CFE_ITALIC;
break;
case IDM_UNDERLINE :
cf.dwMask = CFM_UNDERLINE;
cf.dwEffects ^= CFE_UNDERLINE;
break;
}
// Make the change in the RTF edit control.
//.........................................
SendMessage( hEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf );
SetFocus( hEdit );
}
VOID ChangeAlignment( UINT uCmd )
{
PARAFORMAT pf;
pf.cbSize = sizeof( PARAFORMAT );
pf.dwMask = PFM_ALIGNMENT;
switch( uCmd )
{
case IDM_ALIGNLEFT : pf.wAlignment = PFA_LEFT; break;
case IDM_ALIGNCENTER : pf.wAlignment = PFA_CENTER; break;
case IDM_ALIGNRIGHT : pf.wAlignment = PFA_RIGHT; break;
}
SendMessage( hEdit, EM_SETPARAFORMAT, 0, (LPARAM)&pf );
SetFocus( hEdit );
}
VOID ChangeFont()
{
CHARFORMAT cf;
CHOOSEFONT chFont;
LOGFONT lf;
HDC hDC;
// Retrieve the current font information.
//.......................................
cf.cbSize = sizeof( CHARFORMAT );
SendMessage( hEdit, EM_GETCHARFORMAT, TRUE, (LPARAM)&cf );
memset( &chFont, 0, sizeof( CHOOSEFONT ) );
memset( &lf, 0, sizeof( LOGFONT ) );
// Need a screen DC, use the parent's DC
hDC = GetDC( hMainWnd );
// The RTF Edit control measures in twips, but LOGFONT measures
// in logical units (here, pixels) so we must convert.
// 1 point == 20 twips
// 1 inch == 72 points
// ==> 1 inch == 1440 twips
//.............................................................
lf.lfHeight = MulDiv(cf.yHeight,
GetDeviceCaps(hDC, LOGPIXELSY),
-1440);
ReleaseDC( hMainWnd, hDC );
// Set up the rest of the logfont structure according to the
// information retrieved from the EM_GETCHARFORMAT message.
//..........................................................
if ( cf.dwEffects & CFE_BOLD )
lf.lfWeight = FW_BOLD;
else
lf.lfWeight = FW_NORMAL;
lf.lfItalic = (BOOL)( cf.dwEffects & CFE_ITALIC );
lf.lfUnderline = (BOOL)( cf.dwEffects & CFE_UNDERLINE );
lf.lfCharSet = ANSI_CHARSET;
lf.lfQuality = DEFAULT_QUALITY;
lf.lfPitchAndFamily = cf.bPitchAndFamily;
strcpy( lf.lfFaceName, cf.szFaceName );
// Set up the CHOOSEFONT structure.
//.................................
chFont.lStructSize = sizeof( CHOOSEFONT );
chFont.hwndOwner = hMainWnd;
chFont.lpLogFont = &lf;
chFont.hDC = GetCurrentPrinterDC();
chFont.Flags = CF_BOTH | CF_SCALABLEONLY | CF_WYSIWYG |
CF_NOVECTORFONTS | CF_INITTOLOGFONTSTRUCT;
if ( ChooseFont( &chFont ) )
{
// Set the flags for the values that we are setting.
//..................................................
cf.dwMask = CFM_BOLD | CFM_FACE | CFM_ITALIC |
CFM_OFFSET | CFM_SIZE;
// ChooseFont returns the new point size
// in tenths of a point so multiply by 2 to get
// twips for the richedit control.
//.............................................
cf.yHeight = 2 * chFont.iPointSize;
// Fill in the effects values.
//............................
cf.dwEffects = 0;
if ( lf.lfWeight >= FW_BOLD )
cf.dwEffects |= CFE_BOLD;
if ( lf.lfItalic )
cf.dwEffects |= CFE_ITALIC;
cf.bPitchAndFamily = lf.lfPitchAndFamily;
strcpy( cf.szFaceName, lf.lfFaceName );
// Set the new formatting to the selected text.
//.............................................
SendMessage( hEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf );
}
if ( chFont.hDC )
DeleteDC( chFont.hDC );
SetFocus( hEdit );
}
//***********************************************************
//***********************************************************
// About Dialog Procedure.
//........................
LRESULT CALLBACK About( HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if ( LOWORD(wParam) == IDOK
|| LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
//***********************************************************
//***********************************************************
// Application Initialization
//...........................
BOOL RegisterWin95( CONST WNDCLASS* lpwc )
{
WNDCLASSEX wcex;
wcex.style = lpwc->style;
wcex.lpfnWndProc = lpwc->lpfnWndProc;
wcex.cbClsExtra = lpwc->cbClsExtra;
wcex.cbWndExtra = lpwc->cbWndExtra;
wcex.hInstance = lpwc->hInstance;
wcex.hIcon = lpwc->hIcon;
wcex.hCursor = lpwc->hCursor;
wcex.hbrBackground = lpwc->hbrBackground;
wcex.lpszMenuName = lpwc->lpszMenuName;
wcex.lpszClassName = lpwc->lpszClassName;
// Added elements for Windows 95.
//...............................
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.hIconSm = LoadImage(wcex.hInstance, lpwc->lpszClassName,
IMAGE_ICON, 16, 16,
LR_DEFAULTCOLOR );
return RegisterClassEx( &wcex );
}
int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
MSG msg;
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon (hInstance, lpszAppName);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = lpszAppName;
wc.lpszClassName = lpszAppName;
if ( IS_WIN95 )
{
if ( !RegisterWin95( &wc ) )
return( FALSE );
}
else if ( !RegisterClass( &wc ) )
return( FALSE );
hInst = hInstance;
hMainWnd = CreateWindow( lpszAppName,
lpszTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0,
NULL,
NULL,
hInstance,
NULL
);
if ( !hMainWnd )
return( FALSE );
ShowWindow( hMainWnd, nCmdShow );
UpdateWindow( hMainWnd );
while( GetMessage( &msg, NULL, 0, 0) )
{
if ( hFindWnd && IsDialogMessage( hFindWnd, &msg ) )
continue;
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return( msg.wParam );
}
//***********************************************************
//***********************************************************
// Print Routines
//...............
HDC GetCurrentPrinterDC()
{
HDC hdc = NULL;
// If we have already retrieved printer information,
// create the DC for that printer; otherwise, create
// the DC for the default system printer.
//..................................................
if ( ghDevNames )
{
LPDEVNAMES lpdn = (LPDEVNAMES)GlobalLock( ghDevNames );
LPDEVMODE lpdm = NULL;
if ( ghDevMode )
lpdm = (LPDEVMODE)GlobalLock( ghDevMode );
hdc = CreateDC((LPSTR)lpdn + lpdn->wDriverOffset,
(LPSTR)lpdn + lpdn->wDeviceOffset,
(LPSTR)lpdn + lpdn->wOutputOffset,
lpdm);
}
else
{
PRINTDLG pd = {0};
if ( ghDevMode )
GlobalFree( ghDevMode );
pd.lStructSize = sizeof(pd);
pd.hwndOwner = NULL;
pd.Flags = PD_RETURNDEFAULT | PD_RETURNDC;
if (PrintDlg(&pd))
{
ghDevMode = pd.hDevMode;
ghDevNames = pd.hDevNames;
hdc = pd.hDC;
}
}
return hdc;
}
VOID PrintDocument( PRINTDLG* ppd )
{
FORMATRANGE fr;
DOCINFO di;
UINT nPage, i, j, nCollateCopies;
LONG lTextLength;
char szTitle[MAX_PATH];
LPTSTR szName;
RECT rcTmp;
SetCursor( LoadCursor( NULL, IDC_WAIT ) );
// Clear the abort flag before setting
// abort proc or calling StartDoc.
//....................................
bAbort = FALSE;
// Define the abort function.
//...........................
SetAbortProc( ppd->hDC, AbortProc );
// Start the printing process.
//............................
memset( &di, 0, sizeof( DOCINFO ) );
di.cbSize = sizeof(DOCINFO);
szName = szFileName;
if ( !GetFileTitle( szName, szTitle, sizeof(szTitle) ) )
di.lpszDocName = szTitle;
else
di.lpszDocName = szName;
di.lpszOutput = ( (ppd->Flags & PD_PRINTTOFILE) ? "FILE: " : NULL );
try
{
if ( StartDoc( ppd->hDC, &di ) < 0)
{
szName = "An error occured while trying to print.";
RaiseException( 1, 0, 0, NULL );
}
// Create the modeless Abort dialog box.
//......................................
hDlgAbort = CreateDialog( hInst, "AbortDlg",
hMainWnd, AbortDlg );
if ( !hDlgAbort )
{
szName = "The abort dialog count not be created.";
RaiseException( 2, 0, 0, NULL );
}
}
except ( EXCEPTION_EXECUTE_HANDLER )
{
SetCursor( LoadCursor( NULL, IDC_ARROW ) );
MessageBox( hMainWnd,
szName,
lpszTitle,
MB_OK | MB_ICONHAND );
DeleteDC( ppd->hDC );
return;
}
// Show Abort dialog.
//...................
ShowWindow( hDlgAbort, SW_NORMAL );
UpdateWindow( hDlgAbort );
// Disable the main window
// to prevent the user from a
// menu option while printing.
//............................
EnableWindow( hMainWnd, FALSE );
SetCursor( LoadCursor( NULL, IDC_ARROW ) );
// Find out real size of document in characters.
//..............................................
lTextLength = SendMessage( hEdit,
WM_GETTEXTLENGTH, 0, 0 );
// Render to the same DC as the measure DC.
//.........................................
fr.hdc = ppd->hDC;
fr.hdcTarget = ppd->hDC;
// Set page rect to phys page size in twips
//.........................................
fr.rcPage.left = 0;
fr.rcPage.top = 0;
fr.rcPage.right = MulDiv(
GetDeviceCaps( ppd->hDC, PHYSICALWIDTH ),
1440,
GetDeviceCaps( ppd->hDC, LOGPIXELSX ) );
fr.rcPage.bottom = MulDiv(
GetDeviceCaps( ppd->hDC, PHYSICALHEIGHT ),
1440,
GetDeviceCaps( ppd->hDC, LOGPIXELSY ) );
// Set up 3/4" horizontal and 1" vertical margins,
// with a minimum of 1" printable space in each direction.
//........................................................
fr.rc = fr.rcPage; // initially, the full page
if ( fr.rcPage.right > (2*3*1440/4 + 1440) )
{
fr.rc.left = 3*1440/4;
fr.rc.right -= 3*1440/4;
}
if ( fr.rcPage.bottom > 3*1440 )
{
fr.rc.top = 1440;
fr.rc.bottom -= 1440;
}
// Keep a copy of the page size.
//..............................
rcTmp = fr.rc;
if ( ppd->Flags & PD_COLLATE )
{
nCollateCopies = ppd->nCopies;
ppd->nCopies = 1;
}
else
nCollateCopies = 1;
for ( i=0; i < nCollateCopies && !bAbort; i++ )
{
nPage = 1;
// Set range for the entire document (default)
//............................................
fr.chrg.cpMin = 0;
fr.chrg.cpMax = lTextLength;
// Are we only printing the current selection?
//............................................
if ( ppd->Flags & PD_SELECTION )
{
SendMessage( hEdit, EM_EXGETSEL, 0, (LPARAM)&fr.chrg );
if ( fr.chrg.cpMax >= fr.chrg.cpMin )
lTextLength = fr.chrg.cpMax;
}
// Perform the actual printing.
//.............................
do
{
// Format as much as will fit on a page. The return value
// is the index of the first character on the next page.
//.......................................................
fr.chrg.cpMin = SendMessage( hEdit,
EM_FORMATRANGE,
FALSE,
(LPARAM)&fr);
// Print the page if supposed to.
//...............................
if ( !( (ppd->Flags & PD_PAGENUMS) && nPage < ppd->nFromPage ) )
{
for ( j=0; j < ppd->nCopies && !bAbort; j++ )
{
StartPage( ppd->hDC );
SendMessage( hEdit,
EM_DISPLAYBAND,
0,
(LPARAM)&fr.rc);
EndPage( ppd->hDC );
}
}
// EM_FORMATRANGE modifies fr.rc.bottom, reset here.
//..................................................
fr.rc = rcTmp;
nPage++;
// Are we done?
//.............
if ( (ppd->Flags & PD_PAGENUMS) && nPage > ppd->nToPage )
break;
}
while ( fr.chrg.cpMin < lTextLength && !bAbort );
}
// Restore the RTF Edit controls position.
//........................................
SendMessage( hEdit, EM_FORMATRANGE, TRUE, (LPARAM)NULL );
if ( !bAbort )
EndDoc( ppd->hDC );
// Clean up.
//..........
EnableWindow( hMainWnd, TRUE );
DestroyWindow( hDlgAbort );
DeleteDC( ppd->hDC );
}
BOOL CALLBACK AbortProc( HDC hdc, int Code )
{
MSG msg;
if ( !hDlgAbort )
return( TRUE );
// Message processing for the abort dialog box.
//.............................................
while ( !bAbort && PeekMessage( &msg, NULL, 0, 0, TRUE ) )
if ( !IsDialogMessage( hDlgAbort, &msg ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return( !bAbort );
}
LRESULT CALLBACK AbortDlg( HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam )
{
switch( msg )
{
case WM_COMMAND:
return( bAbort = TRUE );
case WM_INITDIALOG:
{
char szTitle[MAX_PATH];
LPTSTR szName = szFileName;
// Set the focus to the Cancel button.
//....................................
SetFocus( GetDlgItem( hdlg, IDCANCEL ) );
// Retrieve the display name for the file
// and set it in the abort dialog box.
//.......................................
if ( !GetFileTitle( szName, szTitle, sizeof(szTitle) ) )
szName = szTitle;
SetDlgItemText( hdlg, IDC_FILENAME, (LPCTSTR)szName );
}
return( TRUE );
}
return( FALSE );
}